package com.hq.petmap.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

import com.hq.petmap.FileStorage;
import com.hq.petmap.MemoryCache;

public class BackgroundService {
	private final FileStorage _fileStorage;
	private final MemoryCache _memoryCache;
	private final ExecutorService _threadPool;

	public BackgroundService(Context context) {
		_fileStorage = new FileStorage(context);
		_memoryCache = new MemoryCache();
		_threadPool = Executors.newFixedThreadPool(5);
	}

	public Bitmap GetImage(String url, ImageView imageView) {
		Bitmap bitmap = _memoryCache.get(String.valueOf(url.hashCode()));
		if (bitmap == null) {
			_threadPool.submit(new ImageDownLoader(url, _memoryCache,
					_fileStorage, imageView));
		}
		return _memoryCache.get(String.valueOf(url.hashCode()));
	}

	class ImageDownLoader implements Runnable {
		private String _url;
		private MemoryCache _memoryCache;
		private FileStorage _fileStorage;
		private ImageView _imageView;

		ImageDownLoader(String url, MemoryCache memoryCache,
				FileStorage fileStorage, ImageView imageView) {
			this._url = url;
			this._memoryCache = memoryCache;
			this._fileStorage = fileStorage;
			this._imageView = imageView;
		}

		@Override
		public void run() {
			HttpURLConnection connection = null;
			InputStream inputStream = null;
			try {
				String filePath = String.valueOf(_url.hashCode());
				File file = _fileStorage.getFile(filePath);
				if (!file.exists()) {
					URL imageUrl = new URL(_url);
					connection = (HttpURLConnection) imageUrl.openConnection();
					connection.setConnectTimeout(30000);
					connection.setReadTimeout(30000);
					connection.setInstanceFollowRedirects(true);
					inputStream = connection.getInputStream();
					if (inputStream != null) {
						inputStream.mark(inputStream.available());
						_fileStorage.saveFile(file, inputStream);
						inputStream.reset();
					}
				} else {
					inputStream = new FileInputStream(file);
				}
				if (inputStream != null) {
					Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
					if (bitmap != null) {
						_memoryCache.put(filePath, bitmap);
						Activity activity = (Activity) _imageView.getContext();
						ImageUpdate imageUpdate = new ImageUpdate(_imageView,
								bitmap);
						activity.runOnUiThread(imageUpdate);
					} else {
						// Log URL: can't get the bitmap from the InputStream
					}
				} else {
					// Log URL: can't get the inputStream
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (inputStream != null) {
						inputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (connection != null) {
					connection.disconnect();
				}
			}
		}
	}

	class ImageUpdate implements Runnable {
		private ImageView _imageView;
		private Bitmap _bitmap;

		public ImageUpdate(ImageView imageView, Bitmap bitmap) {
			this._imageView = imageView;
			this._bitmap = bitmap;
		}

		public void run() {
			if (_imageView != null) {
				_imageView.setImageBitmap(_bitmap);
			}
		}
	}
}
